import pandas as pd
import numpy as np
from itertools import combinations
from functools import reduce
import datetime
def main(type):
    message = ''
    table_1 = []
    hour = 'H9'
    xlsx_name = 'D:/repos/sicost/模拟服务相关数据.xlsx'
    df_s = pd.read_excel(xlsx_name)
    # df_s_base = pd.read_excel(xlsx_name)
    # xlsx_name = 'D:/repos/sicost/假设24小时副本数量.xlsx'
    # df_s_24 = pd.read_excel(xlsx_name)
    # df_s_base.drop(['COPY_NUM'], axis=1, inplace=True)
    # df_s_hour = df_s_24[['SERVICE_NAME', hour]]
    # v = ['SERVICE_NAME']
    # df_s_merge = pd.merge(df_s_base, df_s_hour, on=v, how='left')
    # df_s_merge.rename(columns={hour: 'COPY_NUM'}, inplace=True)
    #
    # df_s = df_s_merge[['SERVICE_NAME','COPY_NUM','COPY_SIZE','ISOLATION']]
    # 读取已知条件
    xlsx_name = 'D:/repos/sicost/模拟主机相关数据.xlsx'
    df_m = pd.read_excel(xlsx_name)
    # xlsx_name = 'D:/repos/sicost/服务相关数据.xlsx'
    # df_s = pd.read_excel(xlsx_name)
    # 判断需要自隔离的服务拆分副本数是否超过主机数，如果超过说明无法分配
    df_s_tmp = df_s.copy()
    df_s_tmp1 = df_s_tmp[df_s_tmp['ISOLATION'] == 1]
    # 判断是否有需要隔离的服务
    sorted_df_s_tmp1 = df_s_tmp1.sort_values(by='COPY_NUM', ascending=False)
    sorted_df_s_tmp1 = sorted_df_s_tmp1.reset_index(drop=True)
    copy_num_max = sorted_df_s_tmp1.loc[0]['COPY_NUM']
    machine_count = len(df_m.index)
    print('主机数量:')
    print(machine_count)
    df_s_tmp2 = df_s.copy()
    df_s_tmp2 = df_s_tmp2.reset_index(drop=False)
    df_s_tmp2.rename(columns={'index': 'SERVICE_NO'}, inplace=True)
    machine_name_list = df_m['MACHINE_NAME'].tolist()
    if copy_num_max > machine_count:
        message = '可用主机不足！'
        return message, table_1
    # 拼接副本名字COPY_NAME
    # 拼接S1C1，SERVICE_NAME+C+i
    df_c = pd.DataFrame(columns=['COPY_NAME', 'SERVICE_NAME', 'COPY_SIZE', 'ISOLATION', 'COLUMN_INDEX'])
    dict_c = {}
    copy_name_list = []
    for index, row in df_s.iterrows():
        copy_num_tmp = int(row['COPY_NUM'])
        for i in range(1, copy_num_tmp + 1):
            copy_name_tmp = str(row['SERVICE_NAME']) + 'C' + str(i)
            dict_c['COPY_NAME'] = copy_name_tmp
            dict_c['SERVICE_NAME'] = row['SERVICE_NAME']
            dict_c['COPY_SIZE'] = row['COPY_SIZE']
            dict_c['ISOLATION'] = row['ISOLATION']
            dict_c['COLUMN_INDEX'] = len(copy_name_list)
            new_row = pd.Series(dict_c)
            df_c = df_c.append(new_row, ignore_index=True)
            copy_name_list.append(copy_name_tmp)

    # 副本数量
    copy_count = len(copy_name_list)
    print('副本数量:')
    print(copy_count)
    # 生成初始分配矩阵
    x_array = np.zeros((machine_count, copy_count))
    # 生成初始主机资源矩阵
    df_m_tmp = df_m.copy()
    df_m_tmp['RESOURCE_L'] = df_m_tmp['RESOURCE'] * df_m_tmp['U_MAX'] / 100
    # df_m_tmp.drop(['RESOURCE'], axis=1, inplace=True)
    # df_m_tmp.drop(['U_MAX'], axis=1, inplace=True)
    df_m_tmp = df_m_tmp.reset_index(drop=False)
    df_m_tmp.rename(columns={'index': 'ROW_INDEX'}, inplace=True)
    resource_array = df_m_tmp.values
    row_index_list = list(range(machine_count))
    combinations_dict = {}
    combo_count_list = []
    for index, row in sorted_df_s_tmp1.iterrows():
        service_name_tmp = row['SERVICE_NAME']
        copy_num_tmp = int(row['COPY_NUM'])
        combinations_list_tmp = list(combinations(row_index_list, copy_num_tmp))
        combinations_dict[service_name_tmp] = combinations_list_tmp
        combo_count_list.append(len(combinations_list_tmp))
    j_count = reduce((lambda x, y: x * y), combo_count_list, 1)
    i_service_name_list = sorted_df_s_tmp1['SERVICE_NAME'].tolist()
    plan_list = []
    for j in range(0, j_count):
        plan_dict_tmp = {}
        quotient = j
        for k in range(0, len(combo_count_list)):
            service_name_tmp = i_service_name_list[k]
            dividend = quotient  # 被除数
            divisor = combo_count_list[k]  # 除数
            quotient, remainder = divmod(dividend, divisor)
            # print(f"商: {quotient}")
            # print(f"余数: {remainder}")
            plan_dict_tmp[service_name_tmp] = combinations_dict[service_name_tmp][remainder]
            # print('stop')
        plan_list.append(plan_dict_tmp)
    best_x_array = x_array.copy()
    best_resource_array = resource_array.copy()
    df_out = pd.DataFrame(columns=['PLAN_NAME', 'WORDS'])
    dict_out = {}
    for i in range(0, len(plan_list)):
        print(f"方案: {i+1}")
        dict_out['PLAN_NAME'] = '方案:'+str(int(i+1))
        words_list = []
        plan_dict_tmp = plan_list[i]
        words_tmp = '当前反亲和服务分配方案为:' + str(plan_dict_tmp)
        words_list.append(words_tmp)
        tmp_x_array = x_array.copy()
        tmp_resource_array = resource_array.copy()
        for j in range(0, len(i_service_name_list)):
            i_service_name_tmp = i_service_name_list[j]
            df_c_tmp = df_c[df_c['SERVICE_NAME'] == i_service_name_tmp]
            df_c_tmp = df_c_tmp.reset_index(drop=True)
            combo_tmp = plan_dict_tmp[i_service_name_tmp]
            copy_size_tmp = sorted_df_s_tmp1.loc[j]['COPY_SIZE']
            for k in range(0, len(combo_tmp)):
                row_index_tmp = int(combo_tmp[k])
                column_index_tmp = int(df_c_tmp.loc[k]['COLUMN_INDEX'])
                tmp_x_array[row_index_tmp, column_index_tmp] = 1
                tmp_resource_array[row_index_tmp, 4] = tmp_resource_array[row_index_tmp, 4] - copy_size_tmp

            # print('stop')
        # print(tmp_x_array)
        # print(tmp_resource_array)
        # 接一个分配函数
        # 分配方案与当前最优方案对比，保留最优作为新最优
        words_tmp = '调用非反亲和服务分配算法'
        words_list.append(words_tmp)
        df_c_0 = df_c[df_c['ISOLATION'] == 0]
        sorted_df_c_0 = df_c_0.sort_values(by='COPY_SIZE', ascending=False)
        sorted_df_c_0 = sorted_df_c_0.reset_index(drop=True)
        df_m_0 = pd.DataFrame(tmp_resource_array,
                              columns=['ROW_INDEX', 'MACHINE_NAME', 'RESOURCE', 'U_MAX', 'RESOURCE_L'])
        sorted_df_m_0 = df_m_0.sort_values(by='RESOURCE_L', ascending=True)
        sorted_df_m_0 = sorted_df_m_0.reset_index(drop=True)
        tmp_df_m_0 = sorted_df_m_0.copy()
        for index, row in sorted_df_c_0.iterrows():
            # print('副本名:')
            # print(row['COPY_NAME'])
            tmp_machine_name_list = tmp_df_m_0['MACHINE_NAME'].tolist()
            column_index_tmp2 = int(row['COLUMN_INDEX'])
            for l in range(0, len(tmp_machine_name_list)):
                tmp_machine_name = tmp_machine_name_list[l]
                tmp_machine_resource_a = tmp_df_m_0.loc[l]['RESOURCE_L']
                row_index_tmp2 = int(tmp_df_m_0.loc[l]['ROW_INDEX'])
                if row['COPY_SIZE'] <= tmp_machine_resource_a:
                    tmp_x_array[row_index_tmp2, column_index_tmp2] = 1
                    tmp_resource_array[row_index_tmp2, 4] = tmp_resource_array[row_index_tmp2, 4] - row['COPY_SIZE']
                    df_m_02 = pd.DataFrame(tmp_resource_array,
                                           columns=['ROW_INDEX', 'MACHINE_NAME', 'RESOURCE', 'U_MAX', 'RESOURCE_L'])
                    sorted_df_m_02 = df_m_02.sort_values(by='RESOURCE_L', ascending=True)
                    sorted_df_m_02 = sorted_df_m_02.reset_index(drop=True)
                    tmp_df_m_0 = sorted_df_m_02.copy()
                    break
                else:
                    continue
        words_tmp = '将本方案与目前最优方案进行对比'
        words_list.append(words_tmp)
        # print('stop')
        df_m_best = pd.DataFrame(best_resource_array,
                                 columns=['ROW_INDEX', 'MACHINE_NAME', 'RESOURCE', 'U_MAX', 'RESOURCE_L'])
        df_m_1 = pd.DataFrame(tmp_resource_array,
                              columns=['ROW_INDEX', 'MACHINE_NAME', 'RESOURCE', 'U_MAX', 'RESOURCE_L1'])
        df_m_best.drop(['ROW_INDEX'], axis=1, inplace=True)
        df_m_1.drop(['ROW_INDEX'], axis=1, inplace=True)
        df_m_best.drop(['MACHINE_NAME'], axis=1, inplace=True)
        df_m_1.drop(['MACHINE_NAME'], axis=1, inplace=True)
        df_m_best['U'] = (df_m_best['RESOURCE'] * df_m_best['U_MAX'] / 100 - df_m_best['RESOURCE_L']) / df_m_best[
            'RESOURCE'] * 100
        df_m_1['U1'] = (df_m_1['RESOURCE'] * df_m_1['U_MAX'] / 100 - df_m_1['RESOURCE_L1']) / df_m_1['RESOURCE'] * 100
        df_m_best.drop(['RESOURCE_L'], axis=1, inplace=True)
        df_m_1.drop(['RESOURCE_L1'], axis=1, inplace=True)
        df_m_best.drop(['RESOURCE'], axis=1, inplace=True)
        df_m_1.drop(['RESOURCE'], axis=1, inplace=True)
        sorted_df_m_best = df_m_best.sort_values(by='U', ascending=False)
        sorted_df_m_best = sorted_df_m_best.reset_index(drop=True)
        sorted_df_m_1 = df_m_1.sort_values(by='U1', ascending=False)
        sorted_df_m_1 = sorted_df_m_1.reset_index(drop=True)

        sorted_df_m_best = sorted_df_m_best.reset_index(drop=False)
        sorted_df_m_best.rename(columns={'index': 'NO'}, inplace=True)
        sorted_df_m_1 = sorted_df_m_1.reset_index(drop=False)
        sorted_df_m_1.rename(columns={'index': 'NO'}, inplace=True)
        v = ['NO']
        df_m_judge = pd.merge(sorted_df_m_best, sorted_df_m_1, on=v, how='left')

        for index, row in df_m_judge.iterrows():
            if row['U1'] == row['U']:
                print('方案旗鼓相当，继续比较')
                words_tmp = '继续比较'
                words_list.append(words_tmp)
                continue
            elif row['U1'] > row['U'] or row['U1'] == 0:
                print('新方案更好，将新方案替换最优方案')
                words_tmp = '新方案更好，将新方案替换最优方案'
                words_list.append(words_tmp)
                best_x_array = tmp_x_array.copy()
                best_resource_array = tmp_resource_array.copy()
                break
            else:
                words_tmp = '原方案更好，考虑下一方案'
                words_list.append(words_tmp)
                print('原方案更好，考虑下一方案')
                break

        dict_out['WORDS'] = str(words_list)
        new_row = pd.Series(dict_out)
        df_out = df_out.append(new_row, ignore_index=True)
        # print('stop')
    writer = pd.ExcelWriter('plan_words.xlsx')
    df_out.to_excel(writer, sheet_name='Sheet1', index=False)
    writer.save()
    # print('stop')
    # 统计成服务主机
    t_best_x_array = best_x_array.T
    df_best_x = pd.DataFrame(t_best_x_array, columns=machine_name_list)
    # writer = pd.ExcelWriter('best_x' + str(hour) + '.xlsx')
    # df_best_x.to_excel(writer, sheet_name='Sheet1', index=False)
    # writer.save()
    # xlsx_name = 'D:/repos/sicost/best_x.xlsx'
    # df_x = pd.read_excel(xlsx_name)
    df_x = df_best_x.copy()
    df_x['COPY_NAME'] = copy_name_list
    v = ['COPY_NAME']
    df_x_merge = pd.merge(df_x, df_c, on=v, how='left')
    df_x_merge.drop(['COPY_SIZE'], axis=1, inplace=True)
    df_x_merge.drop(['ISOLATION'], axis=1, inplace=True)
    df_x_merge.drop(['COLUMN_INDEX'], axis=1, inplace=True)

    grouped_df = df_x_merge.groupby('SERVICE_NAME').sum()
    grouped_df = grouped_df.reset_index(drop=False)
    grouped_df.rename(columns={'index': 'SERVICE_NAME'}, inplace=True)
    v = ['SERVICE_NAME']
    grouped_df_merge = pd.merge(grouped_df, df_s_tmp2, on=v, how='left')
    sorted_grouped_df_merge = grouped_df_merge.sort_values(by='SERVICE_NO', ascending=True)
    sorted_grouped_df_merge = sorted_grouped_df_merge.reset_index(drop=True)
    # writer = pd.ExcelWriter('best_sx.xlsx')
    writer = pd.ExcelWriter('best_x' + str(hour) + '.xlsx')
    sorted_grouped_df_merge.to_excel(writer, sheet_name='Sheet1', index=False)
    writer.save()
    plan_dict_list = []
    for index, row in sorted_grouped_df_merge.iterrows():
        print(index)
        plan_dict_tmp = {}
        for i in range(0, len(machine_name_list)):
            machine_name_tmp = machine_name_list[i]
            service_count_tmp = row[machine_name_tmp]
            plan_dict_tmp[machine_name_tmp] = service_count_tmp
        print(plan_dict_tmp)
        plan_dict_list.append(str(plan_dict_tmp))

    df_sx_new = sorted_grouped_df_merge[['SERVICE_NAME', 'SERVICE_NO', 'COPY_NUM', 'COPY_SIZE', 'ISOLATION']]
    df_sx_new['PLAN'] = plan_dict_list
    writer = pd.ExcelWriter('best_sx_new' + str(hour) + '.xlsx')
    df_sx_new.to_excel(writer, sheet_name='Sheet1', index=False)
    writer.save()
    table_1 = df_sx_new.to_dict(orient='records')

    return message, table_1

if __name__ == '__main__':
    start = datetime.datetime.now()
    message, table_1 = main(type=1)
    print(message, table_1)
    elapsed = float((datetime.datetime.now() - start).seconds)
    print("Time Used 4 All ----->>>> %f seconds" % (elapsed))
    print('finish')
